/*
 * SimpleDraw.c
 *
 * Example program illustrating a simple use
 * of OpenGL to draw straight lines in 2D, and
 * to draw overlapping triangles in 3D.
 *
 * Author: Samuel R. Buss
 *
 * Software accompanying the book
 *		3D Computer Graphics: A Mathematical Introduction with OpenGL,
 *		by S. Buss, Cambridge University Press, 2003.
 *
 * Software is "as-is" and carries no warranty.  It may be used without
 *   restriction, but if you modify it, please change the filenames to
 *   prevent confusion between different versions.
 * Bug reports: Sam Buss, sbuss@ucsd.edu.
 * Web page: http://math.ucsd.edu/~sbuss/MathCG
 *
 * Version 1.1.  Updated September 28, 2003.
 *    1.1. 9/28/30: Added glEnable(GL_DEPTH_TEST).  Thanks to Rob Wilkens.
 *    1.0. Original version released Spring 2003.
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <GL/glut.h>	// OpenGL Graphics Utility Library
#include <math.h>
#include "translucent.h"

#define ESCAPSE	27

int window;



/*
 * drawScene() handles the animation and the redrawing of the
 *		graphics window contents.
 */
const Pi = 3.1415926535898f;
void drawScene(void)
{
	// Clear the rendering window

	//清除相应的缓冲区（颜色和深度缓冲区）
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glPushMatrix();
	glEnable(GL_DEPTH_TEST);
	glTranslated(-0.5f, 0.0f, -0.5f);
	//红
	glColor4f(1.0f, 0.0f, 0.0f, 0.5f);
	glBegin(GL_QUADS);
	glVertex3f( 1.0f, 1.0f, 0.0f);
	glVertex3f(-1.0f, 1.0f, 0.0f);
	glVertex3f(-1.0f,-1.0f, 0.0f);
	glVertex3f( 1.0f,-1.0f, 0.0f);
	glEnd();
	glPopMatrix();

	glDisable(GL_DEPTH_TEST);
	glPushMatrix();
	glTranslated(0.5f, 0.0f, -1.0f);
	//绿
	glColor4f(0.0f, 1.0f, 0.0f, 0.5f);
	glBegin(GL_QUADS);
	glVertex3f( 1.0f, 1.0f, 0.0f);
	glVertex3f(-1.0f, 1.0f, 0.0f);
	glVertex3f(-1.0f,-1.0f, 0.0f);
	glVertex3f( 1.0f,-1.0f, 0.0f);
	glEnd();
	glPopMatrix();


	glPushMatrix();
	glTranslated(-0.0f, -0.5f, -1.5f);
	//蓝
	glColor4f(0.0f, 0.0f, 1.0f, 0.5f);
	glBegin(GL_QUADS);
	glVertex3f( 1.0f, 1.0f, 0.0f);
	glVertex3f(-1.0f, 1.0f, 0.0f);
	glVertex3f(-1.0f,-1.0f, 0.0f);
	glVertex3f( 1.0f,-1.0f, 0.0f);
	glEnd();
	glPopMatrix();
	// Flush the pipeline.  (Not usually necessary.)
	// 强制刷新缓冲，保证绘图命令将被执行，而不是存储在缓冲区
	glFlush();

}

// Initialize OpenGL's rendering modes
// 初始化OpenGL的绘制模式
void initRendering()
{

	//在涉及到消隐时，都要开启深度测试,当有同样的x，y坐标到来时，比较两者的深度。背景设为最深，默认。
	//glEnable ( GL_DEPTH_TEST );


	// The following commands should induce OpenGL to create round points and 
	//	antialias points and lines.  (This is implementation dependent unfortunately).
	//	以下指令应该导致OpenGL生成圆的点以及抗锯齿的点线
	glEnable(GL_POINT_SMOOTH);
	glEnable(GL_LINE_SMOOTH);
	glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);	// Make round points, not square points 圆点而不是方点
	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);		// Antialias the lines抗锯齿的线
	//将源色和目标色以某种方式混合以产生特效
	glEnable(GL_BLEND);
	//前者表示源因子，后者表示目标因子
	//以下表示把渲染的图像融合到目标区域,結果是亮度不变
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

}

// Called when the window is resized
//		w, h - width and height of the window in pixels.
void resizeWindow(int w, int h)
{
	// Set up the projection view matrix: orthographic projection
	// Determine the min and max values for x and y that should appear in the window.
	// The complication is that the aspect ratio of the window may not match the
	//		aspect ratio of the scene we want to view.
	w = (w==0) ? 1 : w;
	h = (h==0) ? 1 : h;
	// Define the portion of the window used for OpenGL rendering.
	// 定义OpenGL绘制的窗口区域
	glViewport( 0, 0, w, h );	// View port uses whole window
	
	// Now that we know the max & min values for x & y that should be visible in the window,
	//		we set up the orthographic projection.
	// 现在我们知道在窗口中x ＆ y的最大／小值。我们建立正交矩阵
	glMatrixMode( GL_PROJECTION );//指定哪一个矩阵是当前矩阵，参数：指定哪一个矩阵堆栈是下一个矩阵操作的目标
								 // GL_MODELVIEW:对模型视景堆栈
								 // GL_PROJECTION:投影矩阵
								 // GL_TEXTURE:纹理矩阵
	glLoadIdentity();//重置当前指定的矩阵为单位矩阵
	//创建一个正交平行的视景体，用于物体不会因为离屏幕远近而产生大小变换的情况
	//对立情况 glFrustum: 产生透视投影，近大远小
	glOrtho( -4.0f, 4.0f, 4.0f, -4.0f, 0.01f, 100.0f);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

static void
keyPressFunc(unsigned char key, int x, int y)
{
	usleep(100);

	switch(key)
	{
		case ESCAPSE://Escapes
			glutDestroyWindow(window);
			exit(0);
		default:
			break;
	}
}

// Main routine
// Set up OpenGL, define the callbacks and start the main loop
int main( int argc, char** argv )
{
	//初始化GULT库
	glutInit(&argc,argv);

	// The image is not animated so single buffering is OK. 
	// 初始化显示模式， 可以设置颜色模式，缓存模式，是否采用深度等等其它模式
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH );

	// Window position (from top corner), and size (width and hieght)
	// 指定窗口在屏幕中的位置，像素单位，－1表示由窗口管理器来决定窗口的位置
	glutInitWindowPosition( 20, 60 );
	// 指定窗口大小
	glutInitWindowSize( 600, 480 );
	// 创建一个窗口，并設定窗口的标题
	window = glutCreateWindow( "SimpleDraw - Press space bar to toggle images" );


	// Initialize OpenGL as we like it..
	initRendering();

	glutKeyboardFunc(&keyPressFunc);
	// 设置特殊的键盘响应函数 
	// glutSpecialFunc( mySpecialKeyFunc );		// Handles "special" keyboard keys

	// Set up the callback function for resizing windows
	// 调整窗口大小变化的响应函数
	glutReshapeFunc( resizeWindow );

	// Call this for background processing
	// glutIdleFunc( myIdleFunction );

	// call this whenever window needs redrawing
	// 显示输出函数，主要是opengl的绘制
	glutDisplayFunc( drawScene );
	
	// Start the main loop.  glutMainLoop never returns.
	glutMainLoop(  );

	return(0);	// This line is never reached.
}

